﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SimplexEngine
{
    public abstract class Sprite
    {
        public abstract void Draw(SpriteBatch sprite_batch);
    }

    public class TextSprite : Sprite
    {
        public TextSprite(String font_name, String text, Vector2 destination, Vector2 origin, Single rotation, Vector2 scale, Color color)
        {
            // store font
            font = Root.Instance.ContentSystem.GetResource(font_name);

            // store text
            Text = text;
            // destination
            Destination = destination;
            // origin
            Origin = origin;
            // rotation
            Rotation = rotation;
            // scale
            Scale = scale;
            // color
            Color = color;
        }
        
        public override void Draw(SpriteBatch sprite_batch)
        {
            if (Font == null)
                return;

            sprite_batch.DrawString(Font, Text, Destination, Color, Rotation, Origin, Scale, SpriteEffects.None, 0.0f);
        }

        public SpriteFont Font { get { return font == null ? null : font.GetObject<SpriteFont>(); } }
        protected Resource font;

        /// <summary>
        /// destination point
        /// </summary>
        public Vector2 Destination { get; set; }
        /// <summary>
        /// text want to display
        /// </summary>
        public String Text { get; set; }
        /// <summary>
        /// origin of sprite
        /// </summary>
        public Vector2 Origin { get; set; }
        /// <summary>
        /// rotation of sprite
        /// </summary>
        public Single Rotation { get; set; }
        /// <summary>
        /// scale of sprite
        /// </summary>
        public Vector2 Scale { get; set; }
        /// <summary>
        /// color of sprite
        /// </summary>
        public Color Color { get; set; }
    }

    /// <summary>
    /// text area sprite, for 2d text area rendering
    /// </summary>
    public class TextAreaSprite : TextSprite
    {

        public TextAreaSprite(String font_name, String text, Rectangle destination_rectangle, Vector2 origin, Single rotation, Vector2 scale, Color color, Align text_align) : base(font_name, text, new Vector2(), origin, rotation, scale, color)
        {
            // text align
            TextAlign = text_align;

            // destination rectangle
            DestinationRectangle = destination_rectangle;
        }

        /// <summary>
        /// update destination
        /// </summary>
        void Update()
        {
            if (Font == null)
                return;

            // font size
            Vector2 font_size = Font.MeasureString(Text);
            Vector2 destination = new Vector2();

            // horizon align
            int horizon_align = ((int)TextAlign) % 3;
            destination.X = horizon_align == 0 ? DestinationRectangle.Left : (horizon_align == 1 ? DestinationRectangle.Left + (DestinationRectangle.Width - font_size.X) / 2 : DestinationRectangle.Right - font_size.X);

            // vertical align
            int vertical_align = ((int)TextAlign) / 3;
            destination.Y = vertical_align == 0 ? DestinationRectangle.Top : (vertical_align == 1 ? DestinationRectangle.Top + (DestinationRectangle.Height - font_size.Y) / 2 : DestinationRectangle.Bottom - font_size.Y);

            // set destination
            Destination = destination;
        }

        public override void Draw(SpriteBatch sprite_batch)
        {
            Update();
            base.Draw(sprite_batch);
        }

        /// <summary>
        /// destination rectangle
        /// </summary>
        public Rectangle DestinationRectangle { get; set; }

        /// <summary>
        /// align
        /// </summary>
        public enum Align
        {
            TopLeft = 0,
            TopCenter = 1,
            TopRight = 2,
            MiddleLeft = 3,
            MiddleCenter = 4,
            MiddleRight = 5,
            BottomLeft = 6,
            BottomCenter = 7,
            BottomRight = 8
        }

        /// <summary>
        /// text align
        /// </summary>
        public Align TextAlign { get; set; }
    }

    public class ImageSprite : Sprite
    {
        public ImageSprite(String texture_name, Rectangle destination_rectangle, Rectangle source_rectangle, Vector2 origin, Single rotation, Color color, SpriteEffects effects)
        {
            // store image
            texture = Root.Instance.ContentSystem.GetResource(texture_name);

            // source rectangle
            SourceRectangle = source_rectangle;

            // destination rectangle
            DestinationRectangle = destination_rectangle;

            // origin
            Origin = origin;

            // rotation
            Rotation = rotation;

            // color
            Color = color;

            // effects
            Effects = effects;
        }

        public Texture2D Texture { get { return texture == null ? null : texture.GetObject<Texture2D>(); } }

        protected Resource texture;

        public Rectangle DestinationRectangle { get; set; }

        public Rectangle SourceRectangle { get; set; }

        public Vector2 Origin { get; set; }

        public Single Rotation { get; set; }

        public Color Color { get; set; }

        public SpriteEffects Effects { get; set; }

        public override void Draw(SpriteBatch sprite_batch)
        {
            if (Texture == null)
                return;
            // draw sprite
            sprite_batch.Draw(Texture, DestinationRectangle, SourceRectangle, Color, Rotation, Origin, Effects, 0.0f);
        }
    }

    /// <summary>
    /// tile base sprite
    /// </summary>
    public class TileSprite : ImageSprite
    {

        public TileSprite(String texture_name, Rectangle destination_rectangle, int tile_width, int tile_height, Vector2 origin, Single rotation, Color color, SpriteEffects effects) : base(texture_name, destination_rectangle, new Rectangle(), origin, rotation, color, effects)
        {
            // store width and height
            width = tile_width;
            height = tile_height;
        }

        public TileSprite(String texture_name, Rectangle destination_rectangle, Vector2 origin, Single rotation, Color color, SpriteEffects effects, int sprite_columns, int sprite_rows) : base(texture_name, destination_rectangle, new Rectangle(), origin, rotation, color, effects)
        {
            if (sprite_rows > 0) rows = sprite_rows;
            if (sprite_columns > 0) columns = sprite_columns;
        }

        // width
        protected int width = 0;
        // height
        protected int height = 0;

        protected int columns = 1;
        protected int rows = 1;

        /// <summary>
        /// current index
        /// </summary>
        public int Index { get; set; }

        public override void Draw(SpriteBatch sprite_batch)
        {
            if (Texture == null)
                return;

            if (width == 0)
            {
                // calculate width and height
                width = Texture.Width / columns;
                height = Texture.Height / rows;
            }

            int column = Texture.Width / width;
            // calculate source rectangle
            SourceRectangle = new Rectangle((Index % column) * width, (Index / column) * height, width, height);

            base.Draw(sprite_batch);
        }
    }

}
